package org.openkoala.koala.wizard.wizardpage.component;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Map;
import java.util.Map.Entry;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Dialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
import org.openkoala.koala.createvo.TypeDef;
import org.openkoala.koala.utils.MessageBoxUtils;
import org.openkoala.koala.utils.ModuleDependencyUtils;
import org.openkoala.koala.utils.ModuleLayer;
import org.openkoala.koala.widget.Module;
import org.openkoala.koala.widget.ModuleAdd;
import org.openkoala.koala.widget.ModuleUpdate;
import org.openkoala.koala.widget.Project;

/**
 * 添加子模块对话框
 * 
 * @author zyb
 * 
 */
public class AddModuleDialog extends Dialog {

	protected Object result;
	protected Shell shell;

	// 保存功能依赖
	private java.util.List<String> funList = new ArrayList<String>();

	// 保存模块依赖
	private java.util.List<String> dependencyList = new ArrayList<String>();

	// 项目路径
	private String projectPath;

	// 模块实例
	private Module module;

	// 模块添加实例
	private ModuleAdd moduleAdd;

	// 模块更新实例
	private ModuleUpdate moduleUpdate;

	// 操作
	private String operation;

	// 项目实例
	private Project project;

	// 模块类型
	private String moduleType;

	private Text nameTxt;
	
	private Text basePackageText;

	private Label typeLabel;

	private Combo typeCmb;

	private Group moduleGroup;

	private Group functionGroup;
	private Table functionTable;
	private Table moduleTable;
	private TableColumn funNameCol;
	private TableColumn funDescCol;
	private TableColumn moduleNameCol;
	private TableColumn moduleTypeCol;

	/**
	 * Create the dialog.
	 * 
	 * @param parent
	 * @param style
	 */
	public AddModuleDialog(Shell parent, int style) {
		super(parent, style);
	}

	/**
	 * Open the dialog.
	 * 
	 * @return the result
	 */
	public Object open() {
		createContents();
		initControlState();
		shell.open();
		shell.layout();
		Display display = getParent().getDisplay();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch()) {
				display.sleep();
			}
		}
		return result;
	}

	public void setProjectPath(String projectPath) {
		this.projectPath = projectPath;
	}

	public void setModule(Module module) {
		this.module = module;
	}

	public void setModuleUpdate(ModuleUpdate moduleUpdate) {
		this.moduleUpdate = moduleUpdate;
	}

	/**
	 * 初始化控件的状态（用于编辑）
	 */
	private void initControlState() {
		if (module != null) {
			nameTxt.setText(module.getModuleName()); // 模块名称
			nameTxt.setEditable(false);
			basePackageText.setText(module.getBasePackage());
//			typeLabel.setVisible(false);
//			typeCmb.setVisible(false);
			typeCmb.setText(ModuleLayer.getDescriptionByLayer(module.getModuleType()));
			typeCmb.setEnabled(false);
			dependencyList = module.getDependencies();

			TypeDef typeDef = TypeDef.getInstance();
			Map<String, String> map = typeDef.getFunctions(module.getModuleType());
			funList = module.getFunctions();
			for (Entry<String, String> entry : map.entrySet()) {
				TableItem item = new TableItem(functionTable, SWT.NONE);
				item.setText(new String[] { entry.getKey(), entry.getValue() });
				if (funList.contains(entry.getKey())) {
					item.setChecked(true);
				}
			}
			
			for (String dependency : dependencyList) {
				for (int i = 0; i < moduleTable.getItemCount(); i++) {
					if (dependency.equalsIgnoreCase(moduleTable.getItem(i).getText())) {
						moduleTable.getItem(i).setChecked(true);
						continue;
					}
				}
			}
			return;
		}

		if (moduleUpdate != null) {
			nameTxt.setText(moduleUpdate.getModuleName()); // 模块名称
			nameTxt.setEditable(false);
			typeLabel.setVisible(false);
			typeCmb.setVisible(false);
			dependencyList = module.getDependencies();
			funList = module.getFunctions();
			return;
		}

	}

	public void setFunList(java.util.List<String> funList) {
		this.funList = funList;
	}

	public java.util.List<String> getFunList() {
		return funList;
	}

	/**
	 * 获取要添加的模块实例
	 * 
	 * @return
	 */
	public Module getModule() {
		return module;
	}

	/**
	 * 获取要添加的子模块实例
	 * 
	 * @return
	 */
	public ModuleAdd getModuleAdd() {
		return moduleAdd;
	}

	/**
	 * Create contents of the dialog.
	 */
	private void createContents() {
		shell = new Shell(getParent(), SWT.CLOSE | SWT.MIN | SWT.TITLE);
		shell.setImage(null);
		shell.setSize(503, 500);
		shell.setLayout(new FormLayout());

		Label moduleNameLabel = new Label(shell, SWT.NONE);
		FormData fd_moduleNameLabel = new FormData();
		fd_moduleNameLabel.top = new FormAttachment(0, 13);
		moduleNameLabel.setLayoutData(fd_moduleNameLabel);
		moduleNameLabel.setText("模块名称：");

		nameTxt = new Text(shell, SWT.BORDER);
		fd_moduleNameLabel.right = new FormAttachment(nameTxt, -6);
		FormData fd_nameTxt = new FormData();
		fd_nameTxt.right = new FormAttachment(100, -22);
		fd_nameTxt.left = new FormAttachment(0, 76);
		fd_nameTxt.top = new FormAttachment(0, 10);
		nameTxt.setLayoutData(fd_nameTxt);

		Label basePackageLabel = new Label(shell, SWT.NONE);
		FormData fd_basePackageLabel = new FormData();
		fd_basePackageLabel.top = new FormAttachment(moduleNameLabel, 15);
		fd_basePackageLabel.right = new FormAttachment(moduleNameLabel, 0, SWT.RIGHT);
		basePackageLabel.setLayoutData(fd_basePackageLabel);
		basePackageLabel.setText("包路径：");

		basePackageText = new Text(shell, SWT.BORDER);
		FormData fd_basePackageTxt = new FormData();
		fd_basePackageTxt.bottom = new FormAttachment(basePackageLabel, 0, SWT.BOTTOM);
		fd_basePackageTxt.right = new FormAttachment(nameTxt, 0, SWT.RIGHT);
		fd_basePackageTxt.left = new FormAttachment(basePackageLabel, 6);
		basePackageText.setLayoutData(fd_basePackageTxt);
		basePackageText.setText(project.getGroupId() + "." + project.getPackageName());
		
		typeLabel = new Label(shell, SWT.NONE);
		FormData fd_typeLabel = new FormData();
		fd_typeLabel.top = new FormAttachment(basePackageLabel, 18);
		fd_typeLabel.right = new FormAttachment(basePackageLabel, 0, SWT.RIGHT);
		typeLabel.setLayoutData(fd_typeLabel);
		typeLabel.setText("模块类型：");

		typeCmb = new Combo(shell, SWT.READ_ONLY);
		typeCmb.setItems(ModuleLayer.getDescriptions());
		FormData fd_typeCmb = new FormData();
		fd_typeCmb.right = new FormAttachment(nameTxt, 0, SWT.RIGHT);
		fd_typeCmb.left = new FormAttachment(typeLabel, 6);
		fd_typeCmb.bottom = new FormAttachment(typeLabel, 0, SWT.BOTTOM);
		typeCmb.setLayoutData(fd_typeCmb);

		functionGroup = new Group(shell, SWT.NONE);
		functionGroup.setText("功能依赖：");
		FormData fd_functionGroup = new FormData();
		fd_functionGroup.bottom = new FormAttachment(typeLabel, 165, SWT.BOTTOM);
		fd_functionGroup.right = new FormAttachment(nameTxt, 0, SWT.RIGHT);
		fd_functionGroup.top = new FormAttachment(typeLabel, 6);
		fd_functionGroup.left = new FormAttachment(moduleNameLabel, 0, SWT.LEFT);
		functionGroup.setLayoutData(fd_functionGroup);
		
		// Combo值变事件
		typeCmb.addSelectionListener(new SelectionListener() {
			
			@Override
			public void widgetSelected(SelectionEvent e) {
				TypeDef typeDef = TypeDef.getInstance();
				String selectItemText = ModuleLayer.getLayerByDescription(typeCmb.getItem(typeCmb.getSelectionIndex()));
				functionTable.removeAll();
				for (Entry<String, String> entry : typeDef.getFunctions(selectItemText).entrySet()) {
					TableItem item = new TableItem(functionTable, SWT.NONE);
					item.setText(new String[] { entry.getKey(), entry.getValue() });
				}
				funList.clear();
				
				moduleTable.removeAll();
				ModuleDependencyUtils moduleDependencyUtils = new ModuleDependencyUtils(getProject(), selectItemText);
				for (Module theModule : moduleDependencyUtils.getCouldDependencyModules()) {
					TableItem tableItem = new TableItem(moduleTable, SWT.NONE);
					tableItem.setText(new String[] { theModule.getModuleName(), theModule.getModuleType() });
				}
				dependencyList.clear();
			}
			
			@Override
			public void widgetDefaultSelected(SelectionEvent e) {
			}
		});

		moduleGroup = new Group(shell, SWT.NONE);
		moduleGroup.setText("模块依赖：");
		FormData fd_moduleGroup = new FormData();
		fd_moduleGroup.top = new FormAttachment(functionGroup, 9);
		fd_moduleGroup.right = new FormAttachment(nameTxt, 0, SWT.RIGHT);
		
		functionTable = new Table(functionGroup, SWT.BORDER | SWT.CHECK | SWT.FULL_SELECTION | SWT.MULTI);
		functionTable.setHeaderVisible(true);
		functionTable.setBounds(10, 21, 445, 128);
		
		funNameCol = new TableColumn(functionTable, SWT.NONE);
		funNameCol.setWidth(148);
		funNameCol.setText("功能名称");
		
		funDescCol = new TableColumn(functionTable, SWT.NONE);
		funDescCol.setWidth(227);
		funDescCol.setText("功能描述");
		fd_moduleGroup.left = new FormAttachment(moduleNameLabel, 0, SWT.LEFT);
		moduleGroup.setLayoutData(fd_moduleGroup);

		Button okBtn = new Button(shell, SWT.NONE);
		
		okBtn.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				if ("edit".equals(operation)) {
					if (moduleUpdate != null) {
						addOrDelDependencies();
						AddModuleDialog.this.shell.dispose();
						return;
					}
				}
				
				if (!verify()) {
					return;
				}

				if (module == null) {
					module = new Module();
				}
				
				module.setModuleType(ModuleLayer.getLayerByDescription(typeCmb.getItem(typeCmb.getSelectionIndex())));
				module.setModuleName(nameTxt.getText());
				module.setProjectName(project.getAppName());
				module.setBasePackage(basePackageText.getText());
				
				module.setDependencies(dependencyList);
				if (funList.size() > 0) {
					module.setFunctions(funList);
				}
				
				if ((projectPath != null) && (!"".equals(projectPath))) {
					if (moduleAdd == null) {
						moduleAdd = new ModuleAdd();
					}
					moduleAdd.setProjectPath(project.getPath() + "\\" + project.getAppName());
					moduleAdd.setModule(getModule());
				}
				shell.dispose();
			}
			/**
			 * 添加或删除依赖
			 */
			private void addOrDelDependencies() {
				TypeDef typeDef = TypeDef.getInstance();
				Map<String, String> map = typeDef.getFunctions(module.getModuleType());
				java.util.List<String> delList = new ArrayList<String>();
				for (Entry<String, String> entry : map.entrySet()) {
					delList.add(entry.getKey());
				}
				moduleUpdate.setAdd(funList);
				moduleUpdate.setDelete(delList);
				moduleUpdate.setDependencies(AddModuleDialog.this.dependencyList);
			}

			/**
			 * 校验
			 */
			private boolean verify() {
				if (!"editModule".equals(operation)) { // 当添加模块的时候才去校验模块名字是否已经存在
					if (typeCmb.getSelectionIndex() == -1) {
						MessageBoxUtils.showMessage(shell, "提示", "请选择模块类型！");
						return false;
					}
					if ("".equals(nameTxt.getText())) {
						MessageBoxUtils.showMessage(shell, "提示", "请填写模块名称！");
						return false;
					}
					for (Module currentModule : project.getModule()) {
						if (nameTxt.getText().equalsIgnoreCase(currentModule.getModuleName())) {
							MessageBoxUtils.showMessage(shell, "提示", MessageFormat.format("模块名【{0}】已经存在", nameTxt.getText()));
							return false;
						}
					}
				}
				if (!isLegalPackageName(basePackageText.getText())) {
					return false;
				}
				return true;
			}
			
			private boolean isLegalPackageName(String packageName) {
				String[] errorSymbols = new String[]{"!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "-", "=", "+"};
				for (String errorSymbol : errorSymbols) {
					if (packageName.contains(errorSymbol)) {
						MessageBoxUtils.showMessage(shell, "提示", "包路径中含有非法字符！");
						return false;
					}
				}
				
				String[] numberSymbols = new String[]{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
				for (String subPackageName : packageName.split("\\.")) {
					for (String numberSymbol : numberSymbols) {
						if (subPackageName.startsWith(numberSymbol)) {
							MessageBoxUtils.showMessage(shell, "提示", "包路径中包名不能以数字开始！");
							return false;
						}
					}
				}
				
				if (packageName.endsWith(".")) {
					MessageBoxUtils.showMessage(shell, "提示", "包路径不能以“.”结束！");
					return false;
				}
				
				return true;
			}
		});
		
		fd_moduleGroup.bottom = new FormAttachment(100, -43);
		FormData fd_okBtn = new FormData();
		fd_okBtn.left = new FormAttachment(0, 309);
		fd_okBtn.top = new FormAttachment(moduleGroup, 6);
		okBtn.setLayoutData(fd_okBtn);
		okBtn.setText("确定");

		Button cacelBtn = new Button(shell, SWT.NONE);
		cacelBtn.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				module = null;
				shell.dispose();
			}
		});
		
		fd_okBtn.right = new FormAttachment(100, -108);
		FormData fd_cacelBtn = new FormData();
		fd_cacelBtn.right = new FormAttachment(100, -22);
		fd_cacelBtn.left = new FormAttachment(okBtn, 6);
		fd_cacelBtn.bottom = new FormAttachment(moduleGroup, 33, SWT.BOTTOM);
		fd_cacelBtn.top = new FormAttachment(moduleGroup, 6);
		
		moduleTable = new Table(moduleGroup, SWT.BORDER | SWT.FULL_SELECTION | SWT.CHECK | SWT.MULTI);
		moduleTable.setHeaderVisible(true);
		moduleTable.setBounds(10, 22, 445, 128);
		
		moduleNameCol = new TableColumn(moduleTable, SWT.NONE);
		moduleNameCol.setWidth(148);
		moduleNameCol.setText("模块名称");
		
		moduleTypeCol = new TableColumn(moduleTable, SWT.NONE);
		moduleTypeCol.setWidth(234);
		moduleTypeCol.setText("模块类型");
		cacelBtn.setLayoutData(fd_cacelBtn);
		cacelBtn.setText("取消");
		
		// 初始化模块列表 
		if (module != null) {
			ModuleDependencyUtils moduleDependencyUtils = new ModuleDependencyUtils(getProject(), module);
			for (Module theModule : moduleDependencyUtils.getCouldDependencyModules()) {
				TableItem tableItem = new TableItem(moduleTable, SWT.NONE);
				tableItem.setText(new String[] { theModule.getModuleName(), theModule.getModuleType() });
			}
		}
		
//		for (Module currentModule : this.getProject().getModule()) {
//			if (module == null || !currentModule.getModuleName().equalsIgnoreCase(module.getModuleName())) { 
//				TableItem tableItem = new TableItem(moduleTable, SWT.NONE);
//				tableItem.setText(new String[] { currentModule.getModuleName(), currentModule.getModuleType() });
//				if (module != null) { // 编辑状态，解决循环模块引用问题
//					List<String> moduleNames = currentModule.getDependencies();
//					for (String moduleName : moduleNames) {
//						if (module.getModuleName().equals(moduleName)) {
//							tableItem.dispose();
//						}
//					}
//				}
//			}
//		}
		
		functionTable.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				TableItem item = (TableItem) e.item;
				if (item.getChecked()) {
					// 如果被选中则放到List中
					funList.add(item.getText());
					return;
				}
				// 取消选中后则从List中删除
				funList.remove(item.getText());
			}
		});
		
		moduleTable.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				TableItem item = (TableItem) e.item;
				if (item.getChecked()) {
					// 如果被选中则放到List中
					dependencyList.add(item.getText());
					return;
				}
				// 取消选中后则从List中删除
				dependencyList.remove(item.getText());
			}
		});

	}

	public Project getProject() {
		return project;
	}

	public void setProject(Project project) {
		this.project = project;
	}

	public java.util.List<String> getDependencyModuleList() {
		return this.dependencyList;
	}

	public void setOperation(String operation) {
		this.operation = operation;
	}

	public String getModuleType() {
		return moduleType;
	}
}
